/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.foxline.manager.edit;

import br.com.foxline.enums.AnualCorrection;
import br.com.foxline.model.*;
import br.com.foxline.service.*;
import br.com.foxline.util.CoordinateConversion;
import br.com.foxline.util.Msg;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import org.primefaces.context.RequestContext;
import org.primefaces.event.FileUploadEvent;
import org.primefaces.event.SelectEvent;
import org.primefaces.model.DualListModel;
import org.primefaces.model.map.DefaultMapModel;
import org.primefaces.model.map.LatLng;
import org.primefaces.model.map.Marker;
import org.primefaces.model.map.Polygon;

/**
 *
 * @author roniere
 */
@ManagedBean
@ViewScoped
public class ManagerEditEnterprise implements Serializable {

    @EJB
    EnterpriseService enterpriseService;
    @EJB
    ConstructionService constructionService;
    @EJB
    CorrectorService correctorService;
    @EJB
    InterestParcelService interestParcelService;
    @EJB
    TypeLotService typeLotService;
    @EJB
    UserService userService;
    @EJB
    LotService lotService;
    @EJB
    ValueInterestParcelService valueInterestParcelService;
    private Enterprise enterprise;
    private Construction construction;
    private Corrector corrector;
    private City city;
    private City cityNotary;
    private InterestParcel interestParcel;
    private List<InterestParcel> interestParcels;
    private List<Annex> annexs;
    private DualListModel<Corrector> correctorSource;
    private List<Corrector> correctorsAvailable;
    private List<Corrector> correctorsSelected;
    private TypeLot typeLot;
    private List<TypeLot> typeLots;
    private Lot lot;
    private Lot lotCoord;
    private List<Lot> lots;
    private List<Lot> lotsCoord;
    private boolean variable;
    private boolean createLot;
    private int tab = 0;
    private boolean multiplyLot;
    private Integer qtdLot;
    private GeoLocation geoLocation;
    private Coordinate coordinate;
    private List<Coordinate> lstGeoRef;
    private DefaultMapModel polygonModel;
    private DefaultMapModel polygonModelMultiply;
    private String zoomMap = "";
    private String centerMap;
    private Users users;
    private boolean actualUser;

    @PostConstruct
    public void init() {
        Map<String, String> params = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
        String idEnterprise = params.get("e");

        this.enterprise = enterpriseService.find((Long.parseLong(idEnterprise)));
        this.users = this.enterprise.getAdmin();
        this.construction = this.enterprise.getConstruction();

        this.interestParcel = new InterestParcel();
        this.interestParcels = this.enterprise.getInterestParcels();

        this.annexs = this.enterprise.getAnnexs();

        this.correctorsSelected = this.enterprise.getCorrectors();
        this.correctorsAvailable = correctorService.findAll();

        this.correctorsAvailable.removeAll(this.correctorsSelected);

        this.correctorSource = new DualListModel<Corrector>(correctorsAvailable, correctorsSelected);

        this.typeLot = new TypeLot();
        this.typeLots = this.enterprise.getTypeLots();

        this.lot = new Lot();
        this.lotCoord = new Lot();
        this.lots = lotService.lotsByEnterprise(enterprise, null);
        this.lotsCoord = new ArrayList<Lot>();

        this.createLot = false;
        this.geoLocation = new GeoLocation();
        this.coordinate = new Coordinate();
        this.lstGeoRef = new ArrayList<Coordinate>();
        this.polygonModel = new DefaultMapModel();
        this.polygonModelMultiply = new DefaultMapModel();
        this.centerMap = "-2.9136, -41.7577";
        this.zoomMap = "23";


        initMap();

    }

    public void removeGeoRef(Coordinate gf) {
        this.lstGeoRef.remove(gf);
        initMap();
    }

    public void addLotCoord() {
        lotsCoord.add(lotCoord);
        for (Polygon polygon : polygonModel.getPolygons()) {
            polygonModelMultiply.addOverlay(polygon);
        }
    }

    public List<Lot> getLotsCoord() {
        return lotsCoord;
    }

    public void setLotsCoord(List<Lot> lotsCoord) {
        this.lotsCoord = lotsCoord;
    }

    public void initMap() {
        System.err.println(lstGeoRef.size());
        if (lstGeoRef.size() >= 1) {
            polygonModel = new DefaultMapModel();
            Polygon polygon = new Polygon();

            Double centerX = 0D;
            Double centerY = 0D;
            int tam = lstGeoRef.size();
            for (Coordinate geoRef : lstGeoRef) {
                if (geoRef.getLat() != 0.0 && geoRef.getLng() != 0.0) {
                    polygon.getPaths().add(new LatLng(geoRef.getLat(), geoRef.getLng()));

                    Marker marker = new Marker(new LatLng(geoRef.getLat(), geoRef.getLng()));
                    polygonModel.addOverlay(marker);
                    centerX += geoRef.getLat() / tam;
                    centerY += geoRef.getLng() / tam;

                }
            }

            if (tam >= 4 && tam < 6) {
                zoomMap = "18";
            } else if (tam >= 6) {
                zoomMap = "14";
            } else if (tam >= 8) {
                zoomMap = "12";
            }
            centerMap = lstGeoRef.get(0).getLat() + ", " + lstGeoRef.get(0).getLng();

            polygon.setStrokeColor("#FF9900");
            polygon.setFillColor("#FF9900");
            polygon.setStrokeOpacity(0.6);
            polygon.setFillOpacity(0.5);

            polygonModel.addOverlay(polygon);

            for (Marker marker : polygonModel.getMarkers()) {
                marker.setDraggable(true);
            }
        }
    }

    public void converterCoord() {
        System.err.println("CONVERTENDO COORDENADA");
        String lat = coordinate.getConvN();
        String lon = coordinate.getConvE();
        String zona = coordinate.getConvZona();

        try {
            lat = lat.replace(" ", "");
            lon = lon.replace(" ", "");
            if (zona == null) {
                zona = "M";
            }

            CoordinateConversion cc = new CoordinateConversion();

            String UTM = lon.toString().substring(0, 2) + " " + zona + " " + lon.toString().substring(2) + " " + lat.toString();
            System.err.println("CONVERTENDO COORDENADA: " + UTM);
            lstGeoRef.add(new Coordinate(cc.utm2LatLon(UTM)[0], cc.utm2LatLon(UTM)[1], lon, lat, zona));

        } catch (Exception e) {
            Msg.messagemError("Valores incorretos");
        }

    }

    public List<SelectItem> selectTypeBlock() {
        List<SelectItem> items = new ArrayList<SelectItem>();

        if (enterprise != null && enterprise.getQtdBlock() != null) {
            for (int i = 1; i <= enterprise.getQtdBlock(); i++) {
                items.add(new SelectItem(i, "Quadra " + i));
            }
        }
        return items;
    }

    public List<Lot> selectItemsLots() {
        return lots;
    }

    public List<SelectItem> selectAnualCorrection() {
        List<SelectItem> items = new ArrayList<SelectItem>();

        for (AnualCorrection selectItem : AnualCorrection.values()) {
            items.add(new SelectItem(selectItem, selectItem.toString()));
        }
        return items;
    }

    public List<TypeLot> selectTypeLot(String query) {
        List<TypeLot> items = new ArrayList<TypeLot>();
        if (typeLots != null && !typeLots.isEmpty()) {
            return typeLots;
        }
        return items;
    }

    public List<Users> autocompleteUsers(String query) {
        return userService.autocomplete(query);
    }

    public Lot getLotCoord() {
        return lotCoord;
    }

    public void setLotCoord(Lot lotCoord) {
        this.lotCoord = lotCoord;
    }

    public DefaultMapModel getPolygonModelMultiply() {
        return polygonModelMultiply;
    }

    public void setPolygonModelMultiply(DefaultMapModel polygonModelMultiply) {
        this.polygonModelMultiply = polygonModelMultiply;
    }

    public String getCenterMap() {
        return centerMap;
    }

    public void setCenterMap(String centerMap) {
        this.centerMap = centerMap;
    }

    public List<Coordinate> getLstGeoRef() {
        return lstGeoRef;
    }

    public void setLstGeoRef(List<Coordinate> lstGeoRef) {
        this.lstGeoRef = lstGeoRef;
    }

    public DefaultMapModel getPolygonModel() {
        return polygonModel;
    }

    public void setPolygonModel(DefaultMapModel polygonModel) {
        this.polygonModel = polygonModel;
    }

    public String getZoomMap() {
        return zoomMap;
    }

    public void setZoomMap(String zoomMap) {
        this.zoomMap = zoomMap;
    }

    public boolean getMultiplyLot() {
        return multiplyLot;
    }

    public void setMultiplyLot(boolean multiplyLot) {
        this.multiplyLot = multiplyLot;
    }

    public Integer getQtdLot() {
        return qtdLot;
    }

    public void setQtdLot(Integer qtdLot) {
        this.qtdLot = qtdLot;
    }

    public Coordinate getCoordinate() {
        return coordinate;
    }

    public void setCoordinate(Coordinate coordinate) {
        this.coordinate = coordinate;
    }

    public GeoLocation getGeoLocation() {
        return geoLocation;
    }

    public void setGeoLocation(GeoLocation geoLocation) {
        this.geoLocation = geoLocation;
    }

    /*
     * public List<SelectItem> selectTypeLot() { List<SelectItem> items = new
     * ArrayList<SelectItem>();
     *
     * if (typeLots != null && !typeLots.isEmpty()) { System.err.println("TYPE
     * LOT"); for (TypeLot tl : typeLots) { items.add(new SelectItem(tl,
     * tl.getName())); } } return items; }
     *
     *
     * public List<String> selectTypeBlock(String query) { List<String> items =
     * new ArrayList<String>();
     *
     * if (enterprise != null && enterprise.getQtdBlock() != null) { for (int i
     * = 1; i <= enterprise.getQtdBlock(); i++) { items.add(i+""); } } return
     * items; }
     *
     *
     */
    public int getTab() {
        return tab;
    }

    public void setTab(int tab) {
        this.tab = tab;
    }

    public boolean isVariable() {
        return variable;
    }

    public boolean isCreateLot() {
        return createLot;
    }

    public void setCreateLot(boolean createLot) {
        this.createLot = createLot;
    }

    public void setVariable(boolean variable) {
        this.variable = variable;
    }

    public Lot getLot() {
        return lot;
    }

    public void setLot(Lot lot) {
        this.lot = lot;
    }

    public List<Lot> getLots() {
        return lots;
    }

    public void setLots(List<Lot> lots) {
        this.lots = lots;
    }

    public DualListModel<Corrector> getCorrectorSource() {
        return correctorSource;
    }

    public TypeLot getTypeLot() {
        return typeLot;
    }

    public void setTypeLot(TypeLot typeLot) {
        this.typeLot = typeLot;
    }

    public List<TypeLot> getTypeLots() {
        return typeLots;
    }

    public void setTypeLots(List<TypeLot> typeLots) {
        this.typeLots = typeLots;
    }

    public void setCorrectorSource(DualListModel<Corrector> correctorSource) {
        this.correctorSource = correctorSource;
    }

    public List<Corrector> getCorrectorsAvailable() {
        return correctorsAvailable;
    }

    public void setCorrectorsAvailable(List<Corrector> correctorsAvailable) {
        this.correctorsAvailable = correctorsAvailable;
    }

    public List<Corrector> getCorrectorsSelected() {
        return correctorsSelected;
    }

    public void setCorrectorsSelected(List<Corrector> correctorsSelected) {
        this.correctorsSelected = correctorsSelected;
    }

    public List<Enterprise> autocomplete(String query) {
        return enterpriseService.findAll();//.autocomplete(query);
    }

    public List<Annex> getAnnexs() {
        return annexs;
    }

    public void setAnnexs(List<Annex> annexs) {
        this.annexs = annexs;
    }

    public City getCityNotary() {
        return cityNotary;
    }

    public void setCityNotary(City cityNotary) {
        this.cityNotary = cityNotary;
    }

    public Enterprise getEnterprise() {
        return enterprise;
    }

    public InterestParcel getInterestParcel() {
        return interestParcel;
    }

    public void setInterestParcel(InterestParcel interestParcel) {
        this.interestParcel = interestParcel;
    }

    public List<InterestParcel> getInterestParcels() {
        return interestParcels;
    }

    public void setInterestParcels(List<InterestParcel> interestParcels) {
        this.interestParcels = interestParcels;
    }

    public void setEnterprise(Enterprise enterprise) {
        this.enterprise = enterprise;
    }

    public City getCity() {
        return city;
    }

    public void setCity(City city) {
        this.city = city;
    }

    public Construction getConstruction() {
        return construction;
    }

    public void setConstruction(Construction construction) {
        this.construction = construction;
    }

    public Corrector getCorrector() {
        return corrector;
    }

    public void setCorrector(Corrector corrector) {
        this.corrector = corrector;
    }

    public void addInterestParcel() {
        interestParcels.add(interestParcel);
        interestParcel = new InterestParcel();

    }

    public void addTypeLots() {
        typeLots.add(typeLot);
        typeLot = new TypeLot();
    }
    

    public void addLot() {

        if (lot.getSees() != null && enterprise.getPorcBegin() != null) {
            lot.setValueBegin((lot.getSees().multiply(enterprise.getPorcBegin())).setScale(2, RoundingMode.UP));
        }
        if (interestParcels != null) {
            ValueInterestParcel valueInterestParcel = new ValueInterestParcel();
            List<ValueInterestParcel> parcels = new ArrayList<ValueInterestParcel>();

            for (InterestParcel ip : interestParcels) {
                valueInterestParcel = new ValueInterestParcel(ip, calcJuros(ip.getQtd(), ip.getPorc()));
                if (valueInterestParcel.getId() == null) {
                    valueInterestParcelService.save(valueInterestParcel);
                }
                parcels.add(valueInterestParcel);
            }
            lot.setValueInterestParcels(parcels);
        }

        if (lot.getTypeLot() != null) {
            TypeLot find = typeLotService.find(lot.getTypeLot().getId());
            if (find != null) {
                lot.setValueMetre(find.getValue());
                lot.setTypeLot(find);
            }
        }

        if (multiplyLot) {
            lot.setEnterprise(enterprise);
            Lot lotAux = new Lot();
            Integer count = lot.getNum();

            for (int i = 0; i < qtdLot; i++) {
                lotAux = new Lot(lot.getBlock(), count + i, lot.getDimession(), lot.getDimessionX(),
                        lot.getDimessionY(), lot.getTypeLot(), lot.getArea(), lot.getValueMetre(), lot.getSees(),
                        lot.getValueBegin(), lot.getValueInterestParcels(), lot.getGeoLocation(), lot.getStatus(), lot.getEnterprise());
                lotService.update(lotAux);
                lots.add(lotAux);
                lotAux = new Lot();
            }
            lot = new Lot();
        } else {
            lot.setEnterprise(enterprise);
            lotService.update(lot);
            lots.add(lot);
            lot = new Lot();
        }

        Msg.messagemInfo("Empreendimento atualizado com Sucesso !");
    }

    public void removelote(int p) {
        lotService.delete(lots.get(p));
        lots.remove(p);
        RequestContext.getCurrentInstance().execute("bui.hide()");  
    }

    public void finalyLot() {
        for (Lot lot1 : lots) {
            if (lot1.getId() == null) {
                for (ValueInterestParcel vip : lot1.getValueInterestParcels()) {
                    if (vip.getId() == null) {
                        valueInterestParcelService.save(vip);
                    } else {
                        valueInterestParcelService.update(vip);
                    }
                }
                lotService.update(lot1);
            }
        }
        tab = 1;
        lots.clear();
        Msg.messagemInfo("Empreendimento atualizado com Sucesso !");
    }

    public void create() {
        if (this.correctorSource.getTarget() != null && !this.correctorSource.getTarget().isEmpty()) {
            enterprise.setCorrectors(this.correctorSource.getTarget());
        }

        if (interestParcels != null && !interestParcels.isEmpty()) {
            for (InterestParcel ip : interestParcels) {
                if (ip.getId() == null) {
                    interestParcelService.save(ip);
                } else {
                    interestParcelService.update(ip);
                }
            }
            enterprise.setInterestParcels(interestParcels);
        }

        if (typeLots != null && !typeLots.isEmpty()) {
            for (TypeLot tl : typeLots) {
                if (tl.getId() == null) {
                    typeLotService.save(tl);
                } else {
                    typeLotService.update(tl);
                }
            }
            enterprise.setTypeLots(typeLots);
        }
        enterprise.setConstruction(construction);
        enterprise.setCity(city);
        enterprise.setAdmin(users);
        enterprise.setAnnexs(annexs);
        enterpriseService.update(enterprise);
        createLot = true;
        selectTypeBlock();
        tab = 1;
//        init();
    }

    public void removeAnnex(int id) {
        annexs.remove(id);
    }

    public void removeInterest(int id) {
        interestParcels.remove(id);
    }

    public void removeTypeLot(int id) {
        typeLots.remove(id);
    }

    public void removeLot(int id) {
        lotsCoord.remove(id);
    }

    public void handle(FileUploadEvent event) throws IOException {
        handleAux(event.getFile().getContents(), event.getFile().getFileName(),
                event.getFile().getContentType(), event.getFile().getInputstream());
    }

    private void handleAux(byte[] imageBytes, String nome, String tipo, InputStream is) throws IOException {

        byte[] bytes = null;
        Annex annex = new Annex();
        bytes = imageBytes;
        annex.setType(tipo);
        annex.setDescricao(nome);
        if (bytes != null) {
            annexs.add(annex);
            annex = new Annex();
        }

    }

    public void calc() {
        if (!variable) {
            lot.setArea(
                    new BigDecimal(
                    lot.getDimessionX() != null
                    ? lot.getDimessionX().toString() : "1").multiply(
                    new BigDecimal(
                    lot.getDimessionY() != null
                    ? lot.getDimessionY().toString() : "1")));
        }

        System.err.println(lot + " " + lot.getSees() + " " + lot.getArea() + " " + lot.getTypeLot());

        lot.setSees(
                lot.getArea().multiply(
                lot.getTypeLot().getValue()));

    }

    public BigDecimal calcJuros(int qtd, BigDecimal porc) {
        if (enterprise != null && lot.getSees() != null
                && lot != null && enterprise.getPorcBegin() != null && interestParcels != null && !interestParcels.isEmpty()) {
            System.err.println(qtd + " - " + porc);
            return ((lot.getSees().subtract((lot.getSees().multiply(enterprise.getPorcBegin())))).multiply(porc.multiply(new BigDecimal("100"
                    + "")))).divide(new BigDecimal("" + qtd), 2, RoundingMode.UP);
        }
        return BigDecimal.ZERO;
    }

    public void handleSelect(SelectEvent event) {
//        System.err.println(typeLotService.find(((TypeLot) event.getObject()).getId()).getValue());
        if (event != null) {
            lot.setTypeLot(typeLotService.find(((TypeLot) event.getObject()).getId()));
        }
    }

    public void loadUser() {
        if (actualUser) {
            this.users = userService.userByLoginName(userService.getCurrentUser());
        } else {
            this.users = new Users();
        }
    }

    public Users getUsers() {
        return users;
    }

    public void setUsers(Users users) {
        this.users = users;
    }

    public boolean isActualUser() {
        return actualUser;
    }

    public void setActualUser(boolean actualUser) {
        this.actualUser = actualUser;
    }
}
